import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

import { Toast } from "vant";
import { Dialog } from "vant";
Vue.use(Dialog);

export default new Vuex.Store({
  state: {
    // 当前播放歌曲
    currentSong: "",

    // 当前播放状态
    playing: false,

    // 歌曲总时长 s
    duration: 0,

    // 当前播放位置 s
    currentTime: 0,

    // 播放队列
    playlist: [],

    // 歌单足迹
    playlistFootprints: [],

    // 关注的歌单作者列表
    followPlaylistAuthors: [],

    // 订阅歌单列表
    subPlaylists: [],

    // 关注的的歌手
    followSingers: [],

    // 播放模式
    playMode: 0, // 0: 顺序播放, 1: 单曲循环, 2: 随机播放, 3: 列表循环

    // 我喜欢的音乐, 喜欢,比较喜欢,非常喜欢
    myLikeSong: {
      like: [], // 喜欢
      quiteLike: [], // 比较喜欢
      veryLike: [], // 非常喜欢
      // 也可中文键：'喜欢': [], '比较喜欢': [], '非常喜欢': []
    },
  },
  getters: {
    // 当前播放歌曲的URL和ID
    currentSongInfo(state) {
      const { currentSong } = state;
      // 当当前歌曲存在时返回包含url和id的对象，否则返回空字符串的对象
      return currentSong
        ? {
            url: `https://music.163.com/song/media/outer/url?id=${currentSong.id}.mp3`,
            id: currentSong.id,
          }
        : { url: "", id: "" };
    },
  },
  mutations: {
    /**
     * 更新播放位置
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    updateCurrentTime(state, payload) {
      state.currentTime = payload.time;
    },

    /**
     * 更新当前歌曲
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    updateCurrentSong(state, payload) {
      state.currentSong = payload.song;
    },

    /**
     * 更新播放状态
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    updatePlayingState(state, payload) {
      state.playing = payload.bool;
    },

    /**
     * 更新歌曲总时长
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    updateDuration(state, payload) {
      state.duration = payload.dur;
    },

    /**
     * 添加一首音乐到播放队列
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    addSongInPlayList(state, payload) {
      state.playlist.unshift(payload.song);

      // 添加两个属性
      Vue.set(payload.song, "isChecked", false); // 是否选中
      Vue.set(payload.song, "playCount", 0); // 播放次数
    },

    /**
     * 从播放队列删除一首歌
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    deleteOneSongInPlayList(state, payload) {
      const index = state.playlist.findIndex((item) => item === payload.song);
      const DELETE_COUNT = 1;

      // 删除自定义属性
      Vue.delete(state.playlist[index], "isChecked");
      Vue.delete(state.playlist[index], "playCount");

      state.playlist.splice(index, DELETE_COUNT);
      Toast({ message: `已删除${payload.song.name}` });
    },

    /**
     * 下一首
     * @param {object} state vuex的状态
     */
    nextSong(state) {
      console.log("nextSong");

      // 获取当前音乐在播放队列的下标
      const currentIndex = state.playlist.findIndex(
        (o) => o.id === state.currentSong.id
      );

      // 类似轮播图逻辑, 当前播放队列最后一首的下一首就是第一首
      const index =
        currentIndex === state.playlist.length - 1 ? 0 : currentIndex + 1;
      state.currentSong = state.playlist[index];

      /*
        如果播放队列只有一首歌。下一首还是这一首
          TODO  你要不要做单曲循环、随机播放、列表循环?这里不知道干嘛无法继续播放第一首
      */
      // if (state.playlist.length === 1) {
      //   state.currentSong = state.playlist[0];
      //   state.currentTime = 0;

      //   if (state.currentTime === 0) {
      //     setTimeout(() => {
      //       state.playing = true;
      //     });
      //   }
      // }
    },

    /**
     * 上一首
     * @param {object} state vuex的状态
     */
    prevSong(state) {
      console.log("prevSong");

      const currentIndex = state.playlist.findIndex(
        (o) => o.id === state.currentSong.id
      );

      // 当前播放队列第一首的上一首就是最后一首
      const index =
        currentIndex === 0 ? state.playlist.length - 1 : currentIndex - 1;

      state.currentSong = state.playlist[index];
    },

    /**
     * 清除播放队列的所有音乐
     * @param {object} state vuex的状态
     */
    clearAllSongInPlaylist(state) {
      state.playlist = [];
      state.playing = false; // 删除播放队列中所有自定义属性
      state.playlist.forEach((song) => {
        Vue.delete(song, "playCount");
        console.log("删除自定义属性成功");
      });
      // 清空播放队列所有单曲
      state.playlist = [];

      // 清除正在播放的音乐
      state.currentSong = "";
    },

    /**
     * 添加歌单所有歌曲到队列中
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    addAllSongIntoPlaylist(state, payload) {
      Dialog.confirm({
        title: "添加批量音乐至播放队列",
        message: "确认添加所有音乐?",
        confirmButtonColor: "skyblue",

        // 延时0.5秒清除
        beforeClose(action, done) {
          if (action === "confirm") {
            // 避免硬编码
            const DELAY_TIME = 1000;
            setTimeout(done, DELAY_TIME);
          } else {
            done();
          }
        },
      })
        .then(() => {
          state.playlist.push(...payload.list);

          // 去重复
          state.playlist = [...new Set(state.playlist)];
          console.log("finish");

          // 自动播放歌单的第一首
          state.currentSong = payload.list[0];
          Toast.success({
            position: "middle",
            message: "添加成功",
          });
        })
        .catch((reason) => {
          console.log(reason);
          Toast({
            position: "bottom",
            message: "操作失败",
          });
        });
    },

    /**
     * 删除歌单中选中的歌曲
     * @param {object} state vuex的状态
     */
    deleteCheckedSongInPlaylist(state) {
      const checkedSongs = state.playlist.filter((song) => song.isChecked);
      const checkedLength = checkedSongs.length;

      // 如果什么都没选中
      if (checkedLength === 0) {
        return;
      }

      // 提示信息
      const message =
        checkedLength > 1
          ? `确认删除选中的${checkedLength}首歌曲?`
          : "确认删除选中的一首歌曲?";

      Dialog.confirm({
        title: "删除歌曲",
        message,
        confirmButtonColor: "skyblue",
        beforeClose(action, done) {
          if (action === "confirm") {
            const DELAY_TIME = 1000;
            setTimeout(done, DELAY_TIME);
          } else {
            done();
          }
        },
      })
        .then(() => {
          Toast.success({
            message: `已删除${checkedLength}首歌曲`,
            position: "middle",
          });

          state.playlist = state.playlist.filter((song) => !song.isChecked);

          if (checkedLength === 1) {
            state.currentSong = state.playlist[0];
          }
        })
        .catch((reason) => {
          console.log(reason);
          Toast({
            position: "bottom",
            message: "操作失败",
          });
        });
    },

    /**
     * 添加歌单至歌单足迹 (没有提示)
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    addPlaylistFootprints(state, payload) {
      state.playlistFootprints.push(payload.playlist);

      // 相同id只能添加一次
      state.playlistFootprints = [...new Set(state.playlistFootprints)];
    },

    /**
     * 添加歌单至歌单足迹 (有提示)
     * @param {object} state vuex的状态
     * @param {object} payload  载荷
     */
    addPlaylistFootprintsWithTips(state, payload) {
      state.playlistFootprints.push(payload.playlist);

      // 相同id只能添加一次
      state.playlistFootprints = [...new Set(state.playlistFootprints)];

      Toast.success({
        message: "已添加到歌单足迹",
        position: "middle",
      });
    },

    // 从歌单足迹中删除一首歌
    deleteOnePlaylistInPlaylistFootprints(state, payload) {
      const index = state.playlistFootprints.findIndex(
        (foot) => foot.id === payload.item
      );
      const DELETE_COUNT = 1;
      state.playlistFootprints.splice(index, DELETE_COUNT);

      const { name } = payload.item;
      Toast({
        message: `已删除${name}`,
      });
    },

    /**
     * 关注歌单作者
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    addFollowPlaylistAuthors(state, payload) {
      state.followPlaylistAuthors.push(payload.id);
      Toast.success({
        message: "关注成功",
        position: "middle",
      });
    },

    /**
     * 取关歌单作者
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    removeFollowPlaylistAuthors(state, payload) {
      Dialog.confirm({
        message: "确定对ta取消关注?",
        confirmButtonColor: "skyblue",
        beforeClose(action, done) {
          if (action === "confirm") {
            const DELAY_TIME = 1000;
            setTimeout(done, DELAY_TIME);
          } else {
            done();
          }
        },
      })
        .then(() => {
          const index = state.followPlaylistAuthors.findIndex(
            (followId) => followId === payload.id
          );
          const DELETE_COUNT = 1;
          state.followPlaylistAuthors.splice(index, DELETE_COUNT);

          Toast.success({
            message: "取消关注成功",
            position: "middle",
          });
        })
        .catch((reason) => {
          console.log(reason);
          Toast({
            position: "bottom",
            message: "操作失败",
          });
        });
    },

    /**
     * 订阅歌单
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    addSubPlaylists(state, payload) {
      state.subPlaylists.push(payload.id);
      Toast.success({
        message: "订阅成功",
        position: "bottom",
      });
    },

    /**
     * 取消订阅歌单
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    removeSubPlaylists(state, payload) {
      const index = state.subPlaylists.findIndex(
        (followId) => followId === payload.id
      );
      const DELETE_COUNT = 1;
      state.subPlaylists.splice(index, DELETE_COUNT);

      Toast.fail({
        message: "取消订阅成功",
        position: "bottom",
      });
    },

    /**
     * 关注歌手
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    addFollowSinger(state, payload) {
      state.followSingers.push(payload.id);

      // 延迟两秒成功，成功之前弹出loading，模拟真实场景
      Toast.loading({
        message: "操作中",
      });
      setTimeout(() => {
        Toast.success({
          message: "关注成功",
          position: "middle",
        });
      }, 1000);
    },

    /**
     * 取消关注歌手
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    removeFollowSinger(state, payload) {
      const index = state.followSingers.findIndex(
        (followId) => followId === payload.id
      );
      const DELETE_COUNT = 1;

      Dialog.confirm({
        message: "确定对ta取消关注?",
        confirmButtonColor: "skyblue",
        beforeClose(action, done) {
          if (action === "confirm") {
            const DELAY_TIME = 1000;
            setTimeout(done, DELAY_TIME);
          } else {
            done();
          }
        },
      })
        .then(() => {
          state.followSingers.splice(index, DELETE_COUNT);
          Toast.success({
            message: "取消关注成功",
            position: "middle",
          });
        })
        .catch((reason) => {
          console.log(reason);
          Toast({
            position: "bottom",
            message: "操作失败",
          });
        });
    },

    /**
     * 播放队列去重
     * @param {object} state vuex的状态
     */
    newSetPlaylist(state) {
      // 去重
      state.playlist = [...new Set(state.playlist)];
      console.log("去重成功");
    },

    /**
     * 一进去video详情页，暂停音乐
     * @param {object} state vuex的状态
     */
    videoPageCreated(state) {
      state.playing = false;
      console.log("进入了video");
    },

    /**
     * 稍后听
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    addToListenLaterlist(state, payload) {
      state.playlist.push(payload.song);
      Toast.success({
        message: "添加至播放队列成功",
        position: "middle",
      });
    },

    /**
     * 改变播放模式
     * @param {object} state vuex的状态
     * @param {object} payload 载荷
     */
    changePlayMode(state, payload) {
      state.playMode = payload.mode;
    },

    /**
     * 根据播放模式决定怎么播放
     * @param {object} state vuex的状态
     */
    playNextSong(state) {
      const { playlist, currentSong, playMode } = state;
      if (!playlist.length) return;

      const currentIndex = playlist.findIndex(
        (song) => song.id === currentSong?.id
      );

      switch (playMode) {
        case 0: // 顺序播放
          if (currentIndex < playlist.length - 1) {
            state.currentSong = playlist[currentIndex + 1];
          } else {
            state.playing = false; // 播放结束，停止播放
          }
          break;

        case 1: // 单曲循环
          // 重新播放当前歌曲，不改变 currentSong，这里不需要改变状态，由组件控制audio重新播放
          break;

        case 2: // 随机播放
          if (playlist.length > 1) {
            let randomIndex;
            do {
              randomIndex = Math.floor(Math.random() * playlist.length);
            } while (playlist[randomIndex].id === currentSong?.id);
            state.currentSong = playlist[randomIndex];
          }
          break;

        case 3: // 列表循环
          const nextIndex = (currentIndex + 1) % playlist.length;
          state.currentSong = playlist[nextIndex];
          break;
      }
    },

    /**
     * 添加歌曲到指定的喜欢列表
     * @param {object} state - 状态对象
     * @param {object} payload - 传参对象
     * @param {object} payload.song - 要添加的歌曲对象（必须有id）
     * @param {String} payload.type - 要添加到的列表类型：'like'/'quiteLike'/'veryLike'
     */
    addLikeSong(state, payload) {
      const { song, type } = payload;

      // 判断歌曲是否已存在，避免重复添加
      const isExist = state.myLikeSong[type].some(
        (item) => item.id === song.id
      );
      if (!isExist) {
        state.myLikeSong[type].push(song); // 添加到指定列表
      }
    },

    // 可选：对应的删除也可以合并（按需保留）
    removeLikeSong(state, payload) {
      const { songId, type } = payload;
      state.myLikeSong[type] = state.myLikeSong[type].filter(
        (item) => item.id !== songId
      );
    },
  },
  actions: {
    /**
     * 同时提交两个mutation，更新当前歌曲和添加到播放队列
     * @param {object} context 上下文
     * @param {object} payload mutations 的载荷
     *
     * @example
     * $store.commit('updateCurrentSong', { song: item });
     * $store.commit('addSongInPlayList', { song: item })
     */
    updateCurrentSongAndAddSongInPlayList({ commit }, payload) {
      commit("updateCurrentSong", payload);
      commit("addSongInPlayList", payload);
    },

    // 异步处理：显示确认框，确认后调用 mutation
    confirmClearPlaylist({ commit }) {
      return new Promise((resolve) => {
        // 弹出确认框
        Dialog.confirm({
          title: "清空队列",
          message: "确定要清空播放队列?",
          confirmButtonColor: "skyblue",

          // 延时1秒清除
          beforeClose(action, done) {
            if (action === "confirm") {
              done();

              // 作为是否需要关闭父组件状态的标记
              resolve(true);

              commit("clearAllSongInPlaylist");
            } else {
              done();
            }
          },
        }).catch(() => {
          resolve(false);
        });
      });
    },
  },
  modules: {},
});
